package de.idgard.android.proxy;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;

public class IDGardProxyServer implements Runnable {

	private final String VERSION = "1.0";
	private final String HTTP_VERSION = "HTTP/1.1";

	private ServerSocket listen;

	private volatile long bytesread;
	private volatile long byteswritten;
	private volatile int numconnections;

	private boolean enable_cookies_by_default = true;

	public final int DEFAULT_SERVER_PORT = 5557;

	public int port = DEFAULT_SERVER_PORT;
	public InetAddress proxy;
	public int proxy_port = 0;

	public long config_auth = 0;
	public long config_session_id = 0;
	public String config_user = "";
	public String config_password = "";

	public boolean fatalError;
	private String errorMessage;
	private boolean serverRunning = false;

	public boolean useProxy = false;
	public boolean block_urls = false;
	public boolean filter_http = false;
	public boolean debug = false;


	private String idGardServer;

	void initForIDGard() {
		useProxy = true;
		try {
			proxy = InetAddress.getByName(idGardServer);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		filter_http = true;
	}

	void init() {
		writeLog("IDGARD proxy server startup...");

		restoreSettings();

		int i = 5;
		while (i > 0) {
			try {
				listen = new ServerSocket(port);
				break;
			} catch (Exception e1) {
				port += 5 - --i;
			}
		}

		if (fatalError) {
			writeLog(errorMessage);
			return;
		}

	}

	public IDGardProxyServer(String idGardServer, int idGardServerPort, int baseServerPort) {
		this.proxy_port = idGardServerPort;
		this.idGardServer = idGardServer;
		this.port = baseServerPort;
		init();
		initForIDGard();
	}

	private String userAgentString;

	public void setUserAgentString(String userAgentString) {
		this.userAgentString = userAgentString;
	}
	
	public String getUserAgentString() {
		return userAgentString;
	}

	void serve() {

		serverRunning = true;
		writeLog("Server running on port " + this.port);
		try {
			while (serverRunning) {
				Socket client = listen.accept();
				System.out.println("ACCEPTED");
				new IDGardProxyHTTPSession(this, client, userAgentString);
			}
		} catch (Exception e) {
			e.printStackTrace();
			writeLog("Exception in IDGARDServer.serve(): " + e.toString());
		}
	}

	public void run() {
		serve();
	}

	public void setErrorMsg(String a) {
		fatalError = true;
		errorMessage = a;
	}

	public int getHttpMethod(String d) {
		if (startsWith(d, "GET") || startsWith(d, "HEAD")) return 0;
		if (startsWith(d, "POST") || startsWith(d, "PUT")) return 1;
		if (startsWith(d, "CONNECT")) return 2;
		if (startsWith(d, "OPTIONS")) return 3;

		return -1;
	}

	public boolean startsWith(String a, String what) {
		int l = what.length();
		int l2 = a.length();
		return l2 >= l ? a.substring(0, l).equals(what) : false;
	}

	/**
	 * @return the Server response-header field
	 */
	public String getServerIdentification() {
		return "IDGARD/" + getServerVersion();
	}

	public String getServerVersion() {
		return VERSION;
	}

	public void restoreSettings() {

		block_urls = false;
		enable_cookies_by_default = true;
		debug = false;
	}

	public String getHttpVersion() {
		return HTTP_VERSION;
	}

	public void writeLog(String s) {
		writeLog(s, true);
	}

	public void writeLog(String s, boolean new_line) {

		s = new Date().toString() + " " + s;
		System.out.println(s);

	}

	public void addBytesRead(long read) {
		bytesread += read;
	}

	public void addBytesWritten(int written) {
		byteswritten += written;
	}

	public int getServerConnections() {
		return numconnections;
	}

	public long getBytesRead() {
		return bytesread;
	}

	public long getBytesWritten() {
		return byteswritten;
	}

	public void increaseNumConnections() {
		numconnections++;
	}

	public void decreaseNumConnections() {
		numconnections--;
	}

	public void AuthenticateUser(String u, String p) {
		if (config_user.equals(u) && config_password.equals(p)) {
			config_auth = 1;
		} else
			config_auth = 0;
	}

	public String getGMTString() {
		return new Date().toString();
	}

	public boolean enableCookiesByDefault() {
		return this.enable_cookies_by_default;
	}

	public void enableCookiesByDefault(boolean a) {
		enable_cookies_by_default = a;
	}

	public void resetStat() {
		bytesread = 0;
		byteswritten = 0;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public int getPort() {
		return port;
	}

	public boolean isServerRunning() {
		return serverRunning;
	}

	public void shutdownServer() {
		serverRunning = false;
		try {
			listen.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}